package com.erp.erp_ui.warehouse.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.erp.enums.*;
import com.erp.erp_entitys.warehouse.entity.*;
import com.erp.erp_entitys.warehouse.req.OtherOutStockListByPageReq;
import com.erp.erp_entitys.warehouse.req.SelectStockReq;
import com.erp.erp_entitys.warehouse.req.sellOutStockStatistics1Req;
import com.erp.erp_entitys.warehouse.rsp.*;
import com.erp.erp_servers.warehouse.*;
import com.erp.erp_ui.money.req.OperationReq;
import com.erp.erp_ui.warehouse.enums.DataIsValidEnum;
import com.erp.erp_ui.warehouse.enums.DataSourceTitleEnum;
import com.erp.erp_ui.warehouse.req.*;
import com.erp.erp_ui.warehouse.vo.*;
import com.erp.utils.DateUtils;
import com.erp.utils.R;
import com.erp.utils.ResultStatusEnum;
import com.erp.utils.StringUtil;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : OtherOutStockService
 * @Description : 其它出库业务逻辑层
 * @Author : lst
 * @Date: 2020-07-29 09:51
 */
@Service
public class OtherOutStockService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(OtherOutStockService.class);

    /**
     * 其它出库接口
     */
    private final IOtherOutStockService otherOutStockService;

    /**
     * 其它出库明细接口
     */
    private final IOtherOutStockDetailService otherOutStockDetailService;

    /**
     * 库存接口
     */
    private final IStockService stockService;

    /**
     * 库存明细接口
     */
    private final IStockDetailService stockDetailService;

    /**
     * 附件接口
     */
    private final IAnnexService annexService;

    /**
     * 临时附件接口
     */
    private final ITempAnnexService tempAnnexService;

    @Autowired
    public OtherOutStockService(IOtherOutStockService otherOutStockService,
                                IOtherOutStockDetailService otherOutStockDetailService,
                                IStockService stockService,
                                IStockDetailService stockDetailService,
                                IAnnexService annexService,
                                ITempAnnexService tempAnnexService) {
        this.otherOutStockService = otherOutStockService;
        this.otherOutStockDetailService = otherOutStockDetailService;
        this.stockService = stockService;
        this.stockDetailService = stockDetailService;
        this.annexService = annexService;
        this.tempAnnexService = tempAnnexService;
    }


    /**
     * 首页：获取分页信息
     *
     * @param req 查询条件
     * @return 分页信息
     */
    public PageInfo<OtherOutStockListPageVo> getListByPage(OtherOutStockListPageReq req) {
        //初始化查询条件
        OtherOutStockListByPageReq pageReq = new OtherOutStockListByPageReq();
        //赋值
        BeanUtils.copyProperties(req, pageReq);
        //去除前后空格
        if(StringUtils.isNotEmpty(req.getBillNo())){
            pageReq.setBillNo(req.getBillNo().trim());
        }
        //调用接口获取查询结果
        List<OtherOutStockEntity> otherOutStocks = otherOutStockService.getListByPage(pageReq);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(otherOutStocks);
        //初始化回参集合
        List<OtherOutStockListPageVo> pageVos = new ArrayList<>();
        if (CollectionUtils.isEmpty(otherOutStocks)) {
            pageInfo.setList(pageVos);
            return pageInfo;
        }
        for (OtherOutStockEntity other : otherOutStocks) {
            OtherOutStockListPageVo pageVo = new OtherOutStockListPageVo();
            BeanUtils.copyProperties(other, pageVo);
            //日期转换
            pageVo.setOutStockDate(DateUtils.format(other.getOutStockDate(), DateUtils.DATE_PATTERN));
            pageVo.setCreateDate(DateUtils.format(other.getCreateDate(), DateUtils.DATE_PATTERN));
            //状态转换
            pageVo.setStatusStr(OperationStatusEnum.getDescById(other.getStatus()));

            pageVos.add(pageVo);
        }
        pageInfo.setList(pageVos);
        return pageInfo;
    }

    /**
     * 删除出库信息
     *
     * @param req 操作对象
     * @return 删除信息
     */
    @Transactional(rollbackFor = Exception.class)
    public R deleteOtherOutStockInfo(OperationReq req) {
        if (null == req.getId() || null == req.getStatus()) {
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        Integer id = req.getId();
        Integer status = req.getStatus();
        OtherOutStockEntity otherOutStock = new OtherOutStockEntity();
        otherOutStock.setId(id);
        if (OperationStatusEnum.DRAFT_BOX.getId() == status) {
            //草稿箱删除：数据设为垃圾箱，数据回退
            otherOutStock.setStatus(OperationStatusEnum.TRASH_CAN.getId());

        } else if (OperationStatusEnum.TRASH_CAN.getId() == status) {
            //垃圾箱删除：数据设为无效,对应明细数据也将设为无效
            otherOutStock.setValid(DataIsValidEnum.INVALID.getId());
        }
        otherOutStockService.update(otherOutStock);
        //获取出库明细数据
        OtherOutStockDetailEntity otherOutStockDetail = new OtherOutStockDetailEntity();
        otherOutStockDetail.setOutStockId(id);
        otherOutStockDetail.setValid(DataIsValidEnum.VALID.getId());
        //获出库明细
        List<OtherOutStockDetailEntity> otherOutStockDetails = otherOutStockDetailService.queryAll(otherOutStockDetail);
        if (CollectionUtils.isEmpty(otherOutStockDetails)) {
            //没有出库明细,只删除出库主表数据
            return R.build("");
        }
        for (OtherOutStockDetailEntity detail : otherOutStockDetails) {
            //出库数量不为空
            if (StringUtil.isNotEmpty(detail.getOutStockQuantity())) {
                //库存id
                int stockId = detail.getStockId();
                StockEntity stockEntity = stockService.getStockById(stockId);
                //出库数量
                BigDecimal outStockQuantity = detail.getOutStockQuantity();
                //获取库存id
                StockEntity stock = new StockEntity();
                //设置库存id
                stock.setId(stockId);
                //获取库存出库申请数量
                BigDecimal outWarehouseApplyQuantity = stockEntity.getOutWarehouseApply();
                //获取库存可申请数量
                BigDecimal canApplyQuantity = stockEntity.getCanApplyQuantity();
                //只有垃圾箱和草稿箱有删除按钮,草稿箱删除：数据回退，状态为垃圾箱 垃圾箱删除：库存出库申请数量和可申请数量减掉出库数量，状态为草稿箱
                //库存明细修改
                StockDetailEntity stockDetail = new StockDetailEntity();
                stockDetail.setId(detail.getStockDetailId());

                //将出库明细修改
                OtherOutStockDetailEntity otherOutStockReq = new OtherOutStockDetailEntity();
                otherOutStockReq.setId(detail.getId());

                if (OperationStatusEnum.DRAFT_BOX.getId() == status) {
                    //草稿箱删除：数据回退，状态为垃圾箱
                    //回退出库申请数量
                    stock.setOutWarehouseApply(outWarehouseApplyQuantity.subtract(outStockQuantity));
                    //可申请数量
                    if (StringUtil.isNotEmpty(canApplyQuantity)) {
                        //回退可申请数量
                        stock.setCanApplyQuantity(canApplyQuantity.add(outStockQuantity));
                    } else {
                        //回退可申请数量
                        stock.setCanApplyQuantity(outStockQuantity);
                    }

                    //将库存明细设为失效
                    stockDetail.setValid(DataIsValidEnum.INVALID.getId());

                    //将出库明细设为失效
                    otherOutStockReq.setValid(DataIsValidEnum.INVALID.getId());

                } else if (OperationStatusEnum.TRASH_CAN.getId() == status) {
                    //垃圾箱删除：库存出库申请数量和可申请数量减掉调拨数量，状态为草稿箱
                    if (canApplyQuantity.compareTo(outStockQuantity) > -1) {
                        //可申请数量大于等于出库数量
                        if (StringUtil.isNotEmpty(outWarehouseApplyQuantity)) {
                            stock.setOutWarehouseApply(outWarehouseApplyQuantity.add(outStockQuantity));
                        } else {
                            stock.setOutWarehouseApply(outStockQuantity);
                        }
                        //设置可申请数量
                        stock.setCanApplyQuantity(canApplyQuantity.subtract(outStockQuantity));
                    } else {
                        //可申请数量小于出库数量,不能删除
                        return R.buildError(ResultStatusEnum.OTHER_OUT_STOCK_DELETE_ERROR);
                    }

                    //将库存明细设为有效
                    stockDetail.setValid(DataIsValidEnum.VALID.getId());

                    //将出库明细设为有效
                    otherOutStockReq.setValid(DataIsValidEnum.VALID.getId());
                }
                //更新库存数量
                stockService.update(stock);
                //修改库存明细状态
                stockDetailService.update(stockDetail);
                //修改调拨明细状态
                otherOutStockDetailService.update(otherOutStockReq);
            }
        }
        return R.build("");
    }

    /**
     * 出库数据操作接口
     *
     * @param req 操作对象
     *            1.提交审批 2.审批通过 3.审批退回 4.完成 5.还原
     *            箱体：1.草稿箱 2.待批箱 3.已批箱 4.完成箱 5.垃圾箱
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public R operationOtherOutStock(OperationReq req) {
        Integer id = req.getId();
        Integer operation = req.getOperation();
        if (null == id || null == operation) {
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        OtherOutStockEntity otherOutStock = new OtherOutStockEntity();
        //设置id
        otherOutStock.setId(id);
        switch (operation) {
            case 1:
                //提交审批后,状态设为待批箱
                otherOutStock.setStatus(OperationStatusEnum.PENDING_BOX.getId());
                //修改库存信息
                break;
            case 2:
                //审批通过,状态设为已批箱
                otherOutStock.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                updateApprovedBoxStock(req.getId());
                break;
            case 3:
                //审批退回
                break;
            case 4:
                //将状态设为完成
                otherOutStock.setStatus(OperationStatusEnum.COMPLETION_BOX.getId());
                break;
            case 5:
                //点击还原，将状态改为草稿箱
                otherOutStock.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                //更新库存信息：新出库申请数量 = 出库申请数量 + 出库数量
                updateDraftBoxStock(req.getId());
                break;
        }
        //修改数据
        otherOutStockService.update(otherOutStock);
        return R.buildError(ResultStatusEnum.SUCCESS);
    }

    /**
     * 草稿箱:更新库存信息
     *
     * @param id 出库id
     */
    private void updateDraftBoxStock(Integer id) {
        //获取销售库存明细
        OtherOutStockDetailEntity req = new OtherOutStockDetailEntity();
        req.setOutStockId(id);
        req.setValid(DataIsValidEnum.VALID.getId());
        List<OtherOutStockDetailEntity> detailList = otherOutStockDetailService.queryAll(req);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        for (OtherOutStockDetailEntity detail : detailList) {
            //获取出库数量
            BigDecimal outStockQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(detail.getOutStockQuantity())) {
                outStockQuantity = detail.getOutStockQuantity();
            }

            //获取库存明细
            StockEntity stock = stockService.getStockById(detail.getStockId());

            //获取出库申请数量
            BigDecimal outWarehouseApply = new BigDecimal("0");
            if (StringUtil.isNotEmpty(stock.getOutWarehouseApply())) {
                outWarehouseApply = stock.getOutWarehouseApply();
            }

            //新出库申请数量 = 出库申请数量 + 出库数量
            BigDecimal newOutWarehouseApply = outWarehouseApply.add(outStockQuantity);
            stock.setOutWarehouseApply(newOutWarehouseApply);

            //更新库存信息
            stockService.update(stock);
        }

    }

    /**
     * 已批箱:更新库存信息
     *
     * @param id 销售出库id
     */
    private void updateApprovedBoxStock(Integer id) {
        //获取明细
        OtherOutStockDetailEntity req = new OtherOutStockDetailEntity();
        req.setOutStockId(id);
        req.setValid(DataIsValidEnum.VALID.getId());
        List<OtherOutStockDetailEntity> detailList = otherOutStockDetailService.queryAll(req);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        for (OtherOutStockDetailEntity detail : detailList) {
            //获取出库数量
            BigDecimal outStockQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(detail.getOutStockQuantity())) {
                outStockQuantity = detail.getOutStockQuantity();
            }

            //获取库存明细
            StockEntity stock = stockService.getStockById(detail.getStockId());

            //获取实际数量
            BigDecimal realQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(stock.getRealQuantity())) {
                realQuantity = stock.getRealQuantity();
            }

            //获取出库申请数量
            BigDecimal outWarehouseApply = new BigDecimal("0");
            if (StringUtil.isNotEmpty(stock.getOutWarehouseApply())) {
                outWarehouseApply = stock.getOutWarehouseApply();
            }

            //新的实际数量 = 实际数量-出库数量
            BigDecimal newRealQuantity = realQuantity.subtract(outStockQuantity);
            stock.setRealQuantity(newRealQuantity);
            //合同类型为待定
            boolean contractTypeFlag = stock.getContractType().equals(ContractTypeEnum.TO_BE_DETERMINED.getId());
            //合同号为空
            boolean contractNoFlag = StringUtils.isEmpty(stock.getContractNo());
            if(contractTypeFlag && contractNoFlag){
                //待定数据库存的实际可用需要减掉
                //实际可用数量
                BigDecimal realAvailableQuantity = new BigDecimal("0");
                if(StringUtil.isNotEmpty(stock.getRealAvailableQuantity())){
                    realAvailableQuantity = stock.getRealAvailableQuantity();
                }
                //新的实际可用数量 = 出库前实际可用数量 - 出库数量
                BigDecimal newRealAvailableQuantity = realAvailableQuantity.subtract(outStockQuantity);
                stock.setRealAvailableQuantity(newRealAvailableQuantity);
            }

            //新出库申请数量 = 出库申请数量 - 出库数量
            BigDecimal newOutWarehouseApply = outWarehouseApply.subtract(outStockQuantity);
            stock.setOutWarehouseApply(newOutWarehouseApply);

            //更新库存信息
            stockService.update(stock);
        }

    }

    /**
     * 其它出库审批通过
     *
     * @param id 出库id
     */
    private void otherOutStockApproved(Integer id) {
        //初始化查询参数对象
        OtherOutStockDetailEntity detailReq = new OtherOutStockDetailEntity();
        detailReq.setOutStockId(id);
        detailReq.setValid(DataIsValidEnum.VALID.getId());
        List<OtherOutStockDetailEntity> detailList = otherOutStockDetailService.queryAll(detailReq);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        for (OtherOutStockDetailEntity detail : detailList) {
            //获取库存id
            Integer stockId = detail.getStockId();
            //根据库存id获取库存信息
            StockEntity stock = stockService.getStockById(stockId);
            if (null == stock) {
                return;
            }
            //修改最新库存实际数量和实际可用数量
            StockEntity stockReq = new StockEntity();
            //设置修改id
            stockReq.setId(stockId);
            //最新实际数量=库存实际数量-出库数量
            stockReq.setRealQuantity(stock.getRealQuantity().subtract(detail.getOutStockQuantity()));
            //最新实际可用数量=库存实际可用数量-出库数量
            stockReq.setRealAvailableQuantity(stock.getRealAvailableQuantity().subtract(detail.getOutStockQuantity()));
            //调用接口进行修改
            stockService.update(stockReq);
        }
    }


    /**
     * 获取库存信息
     *
     * @param req 查询条件入参
     * @return 库存信息
     */
    public List<OtherOutStockByStockVo> getStockList(StockInfoReq req) {
        //初始化查询信息
        SelectStockReq stockReq = new SelectStockReq();
        //字段赋值
        BeanUtils.copyProperties(req, stockReq);
        //调用库存接口查询库存信息
        List<StockEntity> stocks = stockService.getStockListByQuery(stockReq);
        //初始化回参集合
        List<OtherOutStockByStockVo> stockVos = new ArrayList<>();
        if (stocks.isEmpty()) {
            return stockVos;
        }
        for (StockEntity stock : stocks) {
            //初始化回参对象
            OtherOutStockByStockVo stockVo = new OtherOutStockByStockVo();
            //赋值
            BeanUtils.copyProperties(stock, stockVo);
            //设置库存id
            stockVo.setStockId(stock.getId());
            //设置出库数量(默认为库存实际数量)
            BigDecimal outStockQuantity = stock.getRealQuantity();
            stockVo.setOutStockQuantity(outStockQuantity);
            //设置库存成本(库存成本单价)
            BigDecimal stockCost = stock.getProductUnitPrice();
            stockVo.setStockCost(stockCost);
            //分摊费用单价
            BigDecimal shareCostPrice = stock.getShareCostPrice();
            boolean flag = StringUtil.isNotEmpty(stockCost) && StringUtil.isNotEmpty(outStockQuantity);
            if (flag) {
                //设置成本小计=出库数量*(库存成本+分摊费用单价)
                BigDecimal costNum = stockCost.add(shareCostPrice);
                stockVo.setCostSubtotal(outStockQuantity.multiply(costNum));
            }

            stockVos.add(stockVo);
        }
        return stockVos;
    }

    /**
     * 新增其它出库
     *
     * @param req      新增参数
     * @param creator  创建人
     * @param createNo 创建人编码
     * @throws ParseException
     */
    @Transactional(rollbackFor = Exception.class)
    public R add(AddOtherOutStockReq req, String creator, String createNo) throws ParseException {
        boolean billNoCheckFlag = (null != req.getId() && req.getBillNo().equals(req.getNewBillNo()));
        if (!billNoCheckFlag) {
            //单号做唯一校验
            boolean billNoFlag = checkRepeatBillNo(req.getBillNo());
            if (!billNoFlag) {
                return R.buildError(ResultStatusEnum.BILL_NO_REPEAT);
            }
        }
        if (!CollectionUtils.isEmpty(req.getDetails())) {
            //校验出库数量是否小于等于实际数量（true:是 false:否）
            if (!checkOutStockQuantity(req.getDetails())) {
                return R.buildError(ResultStatusEnum.OUT_STOCK_QUANTITY_CHECK_ERROR);
            }
        }

        //初始化其它出库对象
        OtherOutStockEntity otherOutStock = new OtherOutStockEntity();
        //赋值
        BeanUtils.copyProperties(req, otherOutStock);
        //设置出库日期
        if (StringUtils.isNotEmpty(req.getOutStockDate())) {
            otherOutStock.setOutStockDate(DateUtils.convertStringToDate(req.getOutStockDate(), DateUtils.DATE_PATTERN));
        }
        //设置创建人
        otherOutStock.setCreator(creator);
        //设置创建人编码
        otherOutStock.setCreatorNo(createNo);
        //设置状态,默认为草稿箱
        otherOutStock.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
        //设置数据有效性(0:无效 1:有效)
        otherOutStock.setValid(DataIsValidEnum.VALID.getId());

        if (null == req.getId()) {
            //新增
            //设置创建时间
            otherOutStock.setCreateDate(new Date());
            //调用接口新增
            otherOutStockService.insert(otherOutStock);
        } else {
            //修改
            otherOutStockService.update(otherOutStock);
        }
        if (otherOutStock.getId() == null) {
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }

        insertOutStockDetail(req, otherOutStock.getId(), creator, createNo);

        //添加附件信息
        boolean flag = addAnnex(req.getAnnexList(), otherOutStock.getId(), creator, createNo);
        if (!flag) {
            LOGGER.info("仓库管理-其它出库-批量新增附件异常");
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        //删除临时附件信息
        deleteTempAnnex(req.getAnnexList());
        return R.build(ResultStatusEnum.SUCCESS);
    }

    /**
     * 批量处理临时附件信息，将临时附件设置为失效
     *
     * @param annexReqs
     */
    private void deleteTempAnnex(List<AnnexReq> annexReqs) {
        //没有附件
        if (CollectionUtils.isEmpty(annexReqs)) {
            return;
        }
        //存在附件
        for (AnnexReq annex : annexReqs) {
            if (null != annex.getNews()) {
                //旧附件,不用修改
                continue;
            }
            TempAnnexEntity tempAnnex = new TempAnnexEntity();
            //设置临时附件id
            tempAnnex.setId(annex.getId());
            //设置修改时间
            tempAnnex.setUpdateTime(new Date());
            //将附件设置为失效
            tempAnnex.setValid(0);
            tempAnnexService.update(tempAnnex);
        }

    }

    /**
     * 附件新增
     *
     * @param annexReqs  附件信息
     * @param outStockId 出库id
     * @param operator   操作人
     * @param operatorNo 操作人编码
     * @return 是否新增成功(true : 成功 false : 失败)
     */
    private boolean addAnnex(List<AnnexReq> annexReqs, Integer outStockId, String operator, String operatorNo) {
        try {
            //没有附件,将该id关联的所有附件设为无效
            if (CollectionUtils.isEmpty(annexReqs)) {
                AnnexEntity annexReq = new AnnexEntity();
                annexReq.setParentId(outStockId);
                annexReq.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_OUT_STOCK.getId());
                List<AnnexEntity> annexList = annexService.queryAll(annexReq);
                if (!CollectionUtils.isEmpty(annexList)) {
                    for (AnnexEntity annex : annexList) {
                        AnnexEntity updateAnnex = new AnnexEntity();
                        updateAnnex.setId(annex.getId());
                        //将被删除的附件设为失效
                        updateAnnex.setValid(DataIsValidEnum.INVALID.getId());
                        annexService.update(updateAnnex);
                    }
                }
                return true;
            }
            //存在附件,新增附件信息
            List<AnnexEntity> list = new ArrayList<>();
            //获取旧的附件id集合
            List<Integer> oldIds = new ArrayList<>();
            for (AnnexReq annexReq : annexReqs) {
                if (null != annexReq.getNews()) {
                    //属于旧附件 只取id,不新增
                    oldIds.add(annexReq.getId());
                    continue;
                }
                AnnexEntity annex = new AnnexEntity();
                BeanUtils.copyProperties(annexReq, annex);
                //设置关联模块id
                annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_OUT_STOCK.getId());
                //设置关联模块父id
                annex.setParentId(outStockId);
                //设置上传时间
                annex.setUploadTime(DateUtils.convertStringToDate(annexReq.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置修改时间
                annex.setUpdateTime(new Date());
                //设置操作人
                annex.setOperator(operator);
                //设置操作人编码
                annex.setOperatorNo(operatorNo);
                //设置数据有效
                annex.setValid(1);

                list.add(annex);
            }
            if (oldIds.size() > 0) {
                //通过调拨id获取修改附件信息
                AnnexEntity annex = new AnnexEntity();
                annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_OUT_STOCK.getId());
                annex.setParentId(outStockId);
                //获取上次附件信息
                List<AnnexEntity> annexList = annexService.queryAll(annex);
                if (!CollectionUtils.isEmpty(annexList)) {
                    //获取上次附件id集合
                    List<Integer> oldAnnexIds = annexList.stream().map(p -> p.getId()).collect(Collectors.toList());
                    //得到被删除的附件id
                    Collection collection = new ArrayList(oldAnnexIds);
                    collection.removeAll(oldIds);
                    if (collection.size() > 0) {
                        Iterator<Integer> it = collection.iterator();
                        while (it.hasNext()) {
                            int id = it.next();
                            AnnexEntity annexEntity = new AnnexEntity();
                            annexEntity.setId(id);
                            //将被删除的附件设为失效
                            annexEntity.setValid(DataIsValidEnum.INVALID.getId());

                            annexService.update(annexEntity);
                        }
                    }
                }
            }
            if (!CollectionUtils.isEmpty(list)) {
                //附件批量新增
                int res = annexService.batchInsert(list);
                if (res == list.size()) {
                    return true;
                }
            }
            return true;
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    /**
     * 出库明细新增以及更新库存可申请数量
     *
     * @param req      入参
     * @param id       出库id
     * @param creator  创建人
     * @param createNo 创建人编码
     */
    public void insertOutStockDetail(AddOtherOutStockReq req, int id, String creator, String createNo) {
        if (!CollectionUtils.isEmpty(req.getDetails())) {
            //修改库存信息
            updateStockInfo(req);
            //获取修改明细id集合
            List<Integer> newIds = new ArrayList<>();
            //新增明细集合
            List<OtherOutStockDetailEntity> addDetails = new ArrayList<>();
            for (AddOtherOutStockDetailReq detailReq : req.getDetails()) {
                //初始化明细对象
                OtherOutStockDetailEntity detail = new OtherOutStockDetailEntity();
                //赋值
                BeanUtils.copyProperties(detailReq, detail);
                //设置id
                detail.setOutStockId(id);
                //分摊费用单价
                BigDecimal shareCostPrice = new BigDecimal("0");
                if (StringUtil.isNotEmpty(detailReq.getShareCostPrice())) {
                    shareCostPrice = detailReq.getShareCostPrice();
                }
                //成本单价
                BigDecimal costUnitPrice = new BigDecimal("0");
                if (StringUtil.isNotEmpty(detailReq.getStockCost())) {
                    costUnitPrice = detailReq.getStockCost();
                }
                //获取出库数量
                BigDecimal outStockQuantity = new BigDecimal("0");
                if (StringUtil.isNotEmpty(detailReq.getOutStockQuantity())) {
                    outStockQuantity = detailReq.getOutStockQuantity();
                }
                //设置金额 = (分摊费用单价 + 成本单价)*出库数量
                if (StringUtil.isNotEmpty(costUnitPrice)) {
                    BigDecimal cost = shareCostPrice.add(costUnitPrice);
                    detail.setCostSubtotal(cost.multiply(outStockQuantity));
                }
                //获取托盘入数
                BigDecimal trayNumber = detailReq.getTrayNumber();
                if (StringUtil.isNotEmpty(trayNumber)) {
                    //设置总托盘 = 出库数量除以托盘入数
                    detail.setTotalTray(outStockQuantity.divide(trayNumber, 2, BigDecimal.ROUND_HALF_UP));
                }
                //设置数据有效性(0:无效 1:有效)
                detail.setValid(DataIsValidEnum.VALID.getId());

                //库存明细新增
                int stockDetailId = addStockDetail(detailReq, req.getBillNo(), creator, createNo);

                if (null == detailReq.getId()) {
                    //新增

                    //设置明细库存id
                    detail.setStockDetailId(stockDetailId);
                    addDetails.add(detail);
                } else {
                    //修改

                    //获取明细id
                    newIds.add(detailReq.getId());
                    otherOutStockDetailService.update(detail);
                }

            }

            //处理被删除的出库明细
            handleBeenDeletedTransferDetail(req, id, newIds);

            if (!CollectionUtils.isEmpty(addDetails)) {
                //调用接口保存出库明细
                otherOutStockDetailService.addList(addDetails);
            }
        }
    }

    /**
     * 处理被删除的出库明细
     *
     * @param req    出库明细
     * @param id     出库id
     * @param newIds 修改后未被删除的出库明细id集合
     */
    private void handleBeenDeletedTransferDetail(AddOtherOutStockReq req, int id, List<Integer> newIds) {
        if (null != req.getId()) {
            //修改-找出被删除的出库明细

            OtherOutStockDetailEntity otherOutStockDetailReq = new OtherOutStockDetailEntity();
            //设置出库id
            otherOutStockDetailReq.setOutStockId(id);
            //查询有效数据
            otherOutStockDetailReq.setValid(DataIsValidEnum.VALID.getId());
            //调用接口查询结果
            List<OtherOutStockDetailEntity> otherOutStockDetails = otherOutStockDetailService.queryAll(otherOutStockDetailReq);
            if (!CollectionUtils.isEmpty(otherOutStockDetails)) {
                //获取出库明细id和库存明细id
                Map<String, Map<Integer, Integer>> stockIdAndStockDetailIdMap = getStockIdAndStockDetailIdMap(otherOutStockDetails);
                //获取出库数量
                Map<Integer, BigDecimal> outStockQuantityMap = getOutStockQuantityMap(otherOutStockDetails);
                //获取id集合
                List<Integer> oldIds = otherOutStockDetails.stream().map(p -> p.getId()).collect(Collectors.toList());
                //找出被删除的id
                Collection collection = new ArrayList(oldIds);
                collection.removeAll(newIds);
                if (collection.size() > 0) {
                    //遍历删除被删除的明细
                    Iterator<Integer> ids = collection.iterator();
                    while (ids.hasNext()) {
                        int deletedId = ids.next();
                        Integer stockId = stockIdAndStockDetailIdMap.get("stockIdMap").get(deletedId);
                        //获取库存数据
                        StockEntity stock = stockService.getStockById(stockId);
                        //初始化库存对象
                        StockEntity stockReq = new StockEntity();
                        //设置修改主键
                        stockReq.setId(stockId);
                        //获取出库数量
                        BigDecimal outStockQuantity = outStockQuantityMap.get(deletedId);
                        if (null != req.getStatus() && req.getStatus().equals(OperationStatusEnum.APPROVED_BOX.getId())) {
                            //如果删除的是已批数据,则需要回退 实际数量、可申请数量
                            stockReq.setRealQuantity(stock.getRealQuantity().add(outStockQuantity));
                            stockReq.setRealAvailableQuantity(stock.getRealAvailableQuantity().add(outStockQuantity));
                            stockReq.setCanApplyQuantity(stock.getCanApplyQuantity().add(outStockQuantity));
                        } else {
                            //设置新的可申请数量
                            stockReq.setCanApplyQuantity(stock.getCanApplyQuantity().add(outStockQuantity));
                            //设置新的出库申请数量
                            stockReq.setOutWarehouseApply(stock.getOutWarehouseApply().subtract(outStockQuantity));
                        }
                        //回退删除的出库数量
                        stockService.update(stockReq);

                        OtherOutStockDetailEntity detail = new OtherOutStockDetailEntity();
                        detail.setId(deletedId);
                        detail.setValid(DataIsValidEnum.INVALID.getId());
                        //将删除的出库明细设为无效
                        otherOutStockDetailService.update(detail);
                        //通过出库明细id获取库存库存明细id
                        Integer stockDetailId = stockIdAndStockDetailIdMap.get("stockDetailIdMap").get(deletedId);
                        //将库存明细设为无效
                        StockDetailEntity stockDetail = new StockDetailEntity();
                        stockDetail.setId(stockDetailId);
                        stockDetail.setValid(DataIsValidEnum.INVALID.getId());
                        stockDetailService.update(stockDetail);
                    }
                }
            }
        }
    }

    /**
     * 获取出库数量
     *
     * @param otherOutStockDetails 出库明细对象
     * @return key为出库明细id value为出库数量
     */
    private Map<Integer, BigDecimal> getOutStockQuantityMap(List<OtherOutStockDetailEntity> otherOutStockDetails) {
        //调拨数量
        Map<Integer, BigDecimal> outStockQuantityMap = new HashMap<>(otherOutStockDetails.size());
        for (OtherOutStockDetailEntity otherOutStockDetail : otherOutStockDetails) {
            outStockQuantityMap.put(otherOutStockDetail.getId(), otherOutStockDetail.getOutStockQuantity());
        }
        return outStockQuantityMap;
    }

    /**
     * 获取库存id和库存明细id
     *
     * @param otherOutStockDetails 出库明细对象
     * @return key为调拨明细id value为库存id和库存明细id
     */
    private Map<String, Map<Integer, Integer>> getStockIdAndStockDetailIdMap(List<OtherOutStockDetailEntity> otherOutStockDetails) {
        //获取集合大小
        int size = otherOutStockDetails.size();
        //库存明细id
        Map<Integer, Integer> stockDetailIdMap = new HashMap<>(size);
        //库存id
        Map<Integer, Integer> stockIdMap = new HashMap<>(size);
        for (OtherOutStockDetailEntity otherOutStockDetail : otherOutStockDetails) {
            stockDetailIdMap.put(otherOutStockDetail.getId(), otherOutStockDetail.getStockDetailId());
            stockIdMap.put(otherOutStockDetail.getId(), otherOutStockDetail.getStockId());
        }
        Map<String, Map<Integer, Integer>> map = new HashMap<>(3);
        map.put("stockDetailIdMap", stockDetailIdMap);
        map.put("stockIdMap", stockIdMap);
        return map;
    }


    /**
     * 修改库存信息
     *
     * @param req 修改对象
     */
    private void updateStockInfo(AddOtherOutStockReq req) {
        List<AddOtherOutStockDetailReq> detailList = req.getDetails();
        for (AddOtherOutStockDetailReq detail : detailList) {
            //获取库存id
            Integer stockId = detail.getStockId();
            if (null == stockId) {
                return;
            }
            //获取本次出库数量
            BigDecimal outStockQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(detail.getOutStockQuantity())) {
                outStockQuantity = detail.getOutStockQuantity();
            }
            //获取库存信息
            StockEntity stock = stockService.getStockById(stockId);
            //获取出库申请数量
            BigDecimal outWarehouseApply = new BigDecimal("0");
            if (StringUtil.isNotEmpty(stock.getOutWarehouseApply())) {
                outWarehouseApply = stock.getOutWarehouseApply();
            }
            //获取实际数量
            BigDecimal realQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(stock.getRealQuantity())) {
                realQuantity = stock.getRealQuantity();
            }
            //可申请数量
            BigDecimal canApplyQuantity = new BigDecimal("0");
            if (StringUtil.isNotEmpty(stock.getCanApplyQuantity())) {
                canApplyQuantity = stock.getCanApplyQuantity();
            }

            if (null == req.getId()) {
                //新增
                //1.保存到草稿箱：库存实际数量不变 新出库申请数量 = 本次出库数量+出库申请数量
                //新出库申请数量
                BigDecimal newOutWarehouseApply = outStockQuantity.add(outWarehouseApply);
                stock.setOutWarehouseApply(newOutWarehouseApply);
                //2.新的可申请数量 = 老的可申请数量 - 出库数量
                BigDecimal newCanApplyQuantity = canApplyQuantity.subtract(outStockQuantity);
                stock.setCanApplyQuantity(newCanApplyQuantity);
            } else {
                //修改
                if (null == req.getStatus()) {
                    return;
                }
                if(null == detail.getId()){
                    //修改时 新增产品信息
                    //1.保存到草稿箱：库存实际数量不变 新出库申请数量 = 本次出库数量+出库申请数量
                    //新出库申请数量
                    BigDecimal newOutWarehouseApply = outStockQuantity.add(outWarehouseApply);
                    stock.setOutWarehouseApply(newOutWarehouseApply);
                    //2.新的可申请数量 = 老的可申请数量 - 出库数量
                    BigDecimal newCanApplyQuantity = canApplyQuantity.subtract(outStockQuantity);
                    stock.setCanApplyQuantity(newCanApplyQuantity);
                }else {
                    //修改时 修改产品信息
                    //获取修改前单据信息
                    OtherOutStockDetailEntity detailEntity = otherOutStockDetailService.queryById(detail.getId());
                    //获取修改前出库数量
                    BigDecimal oldOutStockQuantity = new BigDecimal("0");
                    if (StringUtil.isNotEmpty(detailEntity.getOutStockQuantity())) {
                        oldOutStockQuantity = detailEntity.getOutStockQuantity();
                    }

                    if (req.getStatus() == OperationStatusEnum.DRAFT_BOX.getId()) {
                        //草稿箱修改:保存到草稿箱
                        //库存实际数量不变 新出库申请数量 = 本次出库数量+（出库申请数量-修改前出库数量）
                        //出库申请数量-修改前出库数量
                        BigDecimal quantity = outWarehouseApply.subtract(oldOutStockQuantity);
                        //新出库申请数量 = 本次出库数量+（出库申请数量-修改前出库数量）
                        BigDecimal newOutWarehouseApply = outStockQuantity.add(quantity);
                        stock.setOutWarehouseApply(newOutWarehouseApply);
                    } else if (req.getStatus() == OperationStatusEnum.APPROVED_BOX.getId()) {
                        //已批箱修改:保存到草稿箱
                        //新实际数量 = 实际数量+修改前出库数量
                        BigDecimal newRealQuantity = realQuantity.add(oldOutStockQuantity);
                        stock.setRealQuantity(newRealQuantity);

                        //新出库申请数量 = 出库申请数量+本次出库数量
                        BigDecimal newOutWarehouseApply = outWarehouseApply.add(outStockQuantity);
                        stock.setOutWarehouseApply(newOutWarehouseApply);
                    }

                    //差值 = 本次出库数量 - 修改前出库数量
                    BigDecimal subNum = outStockQuantity.subtract(oldOutStockQuantity);
                    //新可申请数量 = 老的可申请数量 - 差值
                    BigDecimal newCanApplyQuantity = canApplyQuantity.subtract(subNum);
                    stock.setCanApplyQuantity(newCanApplyQuantity);
                }

            }
            //调用库存接口保存新的出库数量
            stockService.update(stock);
        }

    }

    /**
     * 新增库存明细
     *
     * @param detailReq 出库明细
     * @param billNo    单号
     * @param creator   创建人
     * @param createNo  创建人编码
     */
    private int addStockDetail(AddOtherOutStockDetailReq detailReq, String billNo, String creator, String createNo) {
        //初始化库存明细对象
        StockDetailEntity stockDetail = new StockDetailEntity();
        //赋值
        BeanUtils.copyProperties(detailReq, stockDetail);
        //设置标题
        stockDetail.setTitle(DataSourceTitleEnum.OTHER_OUT_STOCK.getDesc());
        //设置单据编号
        stockDetail.setInvoiceNumber(billNo);
        //设置单价
        stockDetail.setUnitPrice(detailReq.getStockCost());
        //设置数量
        stockDetail.setQuantity(detailReq.getOutStockQuantity());
        //设置模块id
        stockDetail.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_OUT_STOCK.getId());
        //设置创建人
        stockDetail.setInStorePerson(creator);
        //设置创建人编码
        stockDetail.setInStoreCode(createNo);
        //设置操作人
        stockDetail.setOperator(creator);
        //设置操作人编码
        stockDetail.setOperationCode(createNo);
        if (null == detailReq.getId()) {
            //新增

            //设置创建时间
            stockDetail.setCreateDate(new Date());
            //设置有效性
            stockDetail.setValid(DataIsValidEnum.VALID.getId());
            stockDetailService.insert(stockDetail);

        } else {
            //修改

            stockDetail.setId(detailReq.getStockDetailId());
            stockDetailService.update(stockDetail);
        }

        return stockDetail.getId();
    }

    /**
     * 校验单号是否存在
     *
     * @param billNo 单号
     * @return true:不重复 false:重复
     */
    private boolean checkRepeatBillNo(String billNo) {
        OtherOutStockEntity req = new OtherOutStockEntity();
        req.setBillNo(billNo);
        List<OtherOutStockEntity> list = otherOutStockService.queryAll(req);
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }
        return false;
    }

    /**
     * 校验出库数量是否小于等于实际数量（true:是 false:否）
     *
     * @param list 其它出库明细集合
     * @return boolean
     */
    private boolean checkOutStockQuantity(List<AddOtherOutStockDetailReq> list) {
        for (AddOtherOutStockDetailReq addOtherOutStockDetailReq : list) {
            //获取库存id
            int stockId = addOtherOutStockDetailReq.getStockId();
            //获取库存信息
            StockEntity stockEntity = stockService.getStockById(stockId);
            //实际数量(库存可申请数量)
            BigDecimal realQuantity = stockEntity.getCanApplyQuantity();
            boolean flag = true;
            if (null == addOtherOutStockDetailReq.getId()) {
                //修改时 新增产品
                //出库数量必须小于等于实际数量
                flag = addOtherOutStockDetailReq.getOutStockQuantity().compareTo(realQuantity) < 1;
            } else {
                //修改时 修改产品
                //获取修改前 出库产品信息
                OtherOutStockDetailEntity product = otherOutStockDetailService.queryById(addOtherOutStockDetailReq.getId());
                //获取修改前 出库数量
                BigDecimal oldOutStockQuantity = new BigDecimal("0");
                if (StringUtil.isNotEmpty(product.getOutStockQuantity())) {
                    oldOutStockQuantity = product.getOutStockQuantity();
                }
                BigDecimal newNum = realQuantity.add(oldOutStockQuantity);
                flag = addOtherOutStockDetailReq.getOutStockQuantity().compareTo(newNum) < 1;
            }
            if (!flag) {
                return false;
            }

        }
        return true;
    }

    /**
     * 其它出库审核
     *
     * @param outStockId 其它出库id
     */
    @Transactional(rollbackFor = Exception.class)
    public void checkOtherOutStock(Integer outStockId) {
        if (null == outStockId) {
            LOGGER.warn("仓库管理-其它出库-其它出库审核异常,出库id不能为空");
        }
        //获取其它出库信息
        OtherOutStockEntity otherOutStockEntity = otherOutStockService.queryById(outStockId);
        //初始化查询参数
        OtherOutStockDetailEntity otherOutStockDetailReq = new OtherOutStockDetailEntity();
        //设置其它出库id
        otherOutStockDetailReq.setOutStockId(outStockId);
        //查询其它出库明细
        List<OtherOutStockDetailEntity> otherOutStockDetails = otherOutStockDetailService.queryAll(otherOutStockDetailReq);
        if (otherOutStockDetails.isEmpty()) {
            return;
        }
        for (OtherOutStockDetailEntity otherOutStockDetail : otherOutStockDetails) {
            //库存id
            int stockId = otherOutStockDetail.getStockId();
            //获取库存信息
            StockEntity stockEntity = stockService.getStockById(stockId);
            //实际数量
            BigDecimal realQuantity = stockEntity.getRealQuantity();
            //出库数量
            BigDecimal outStockQuantity = otherOutStockDetail.getOutStockQuantity();
            //初始化库存对象
            StockEntity stock = new StockEntity();
            //设置库存id
            stock.setId(stockId);
            if (StringUtil.isNotEmpty(realQuantity) && StringUtil.isNotEmpty(outStockQuantity)) {
                //更新实际数量(实际数量-出库数量)
                BigDecimal num = realQuantity.subtract(outStockQuantity);
                stock.setRealQuantity(num);
                //设置实际可用数量
                stock.setRealAvailableQuantity(num);
            }
            //调用库存接口进行库存信息修改
            stockService.update(stock);

            //生成库存明细信息
            //初始化库存明细
            StockDetailEntity stockDetail = new StockDetailEntity();
            //库存id
            stockDetail.setStockId(stockId);
            //标题(来源其它出库)
            stockDetail.setTitle(DataSourceTitleEnum.OTHER_OUT_STOCK.getDesc());
            //模块id(来源其它出库)
            stockDetail.setModuleId(DataSourceTitleEnum.OTHER_OUT_STOCK.getId());
            //单据编号(其它出库出库单号)
            stockDetail.setInvoiceNumber(otherOutStockEntity.getBillNo());
            //仓库编码
            stockDetail.setWarehouseCode(otherOutStockDetail.getWarehouseCode());
            //仓库名称

            //产品编码
            stockDetail.setProductCode(otherOutStockDetail.getProductCode());
            //规格编码
            stockDetail.setSpecificationCode(otherOutStockDetail.getSpecificationCode());
            //颜色
            stockDetail.setColor(stockEntity.getColor());
            //成本单价(其它出库中的库存成本)
            stockDetail.setUnitPrice(otherOutStockDetail.getStockCost());
            //成本金额=(其它出库中的成本小计)
            stockDetail.setMoney(otherOutStockDetail.getCostSubtotal());
            //数量
            stockDetail.setQuantity(otherOutStockDetail.getOutStockQuantity());
            //标准单位数量
            stockDetail.setStandardUnitQuantity(otherOutStockDetail.getOutStockQuantity());
            //标准单位
            stockDetail.setStandardUnit(otherOutStockDetail.getProductUnit());
            //创建时间
            stockDetail.setCreateDate(new Date());
            //入库人
            stockDetail.setInStorePerson(otherOutStockEntity.getOutStockPerson());
            //操作人
            stockDetail.setOperator(otherOutStockEntity.getCreator());
            //操作人编码
            stockDetail.setOperationCode(otherOutStockEntity.getCreatorNo());
            //规格说明
            stockDetail.setProductSpecExplanation(otherOutStockDetail.getSpecificationExplanation());
            //备注
            stockDetail.setMemo(otherOutStockDetail.getMemo());

            //新增库存明细
            stockDetailService.insert(stockDetail);

        }

        //修改其它出库状态为已批
        OtherOutStockEntity otherOutStock = new OtherOutStockEntity();
        otherOutStock.setId(outStockId);
        otherOutStock.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
        otherOutStockService.update(otherOutStock);
    }

    /**
     * 获取库存信息
     *
     * @param req 查询参数
     * @return 库存对象集合
     */
    public PageInfo<OtherOutStockProductVo> getStockInfo(OtherOutStockProductReq req) {
        //初始化回参集合
        List<OtherOutStockProductVo> productVos = new ArrayList<>();
        //获取库存信息，默认实际数量大于0,可申请数量大于0
        SelectStockReq selectStockReq = new SelectStockReq();
        //赋值
        BeanUtils.copyProperties(req, selectStockReq);
        //去除前后空格
        if(StringUtils.isNotEmpty(req.getSaleContractNo())){
            //销售合同号
            selectStockReq.setContractNo(req.getSaleContractNo().trim());
        }
        if(StringUtils.isNotEmpty(req.getPurchaseNo())){
            selectStockReq.setPurchaseNo(req.getPurchaseNo().trim());
        }
        if(StringUtils.isNotEmpty(req.getProductCode())){
            selectStockReq.setProductCode(req.getProductCode().trim());
        }
        if(StringUtils.isNotEmpty(req.getSpecificationCode())){
            selectStockReq.setSpecificationCode(req.getSpecificationCode().trim());
        }
        if(StringUtils.isNotEmpty(req.getLotNo())){
            selectStockReq.setLotNo(req.getLotNo().trim());
        }
        //实际数量大于零
        selectStockReq.setZeroStock(0);
        //可申请数量必须大于零
        selectStockReq.setZeroCanApplyQuantity(0);
        //查询库存信息
        List<StockEntity> stocks = stockService.getStockListByQuery(selectStockReq);
        PageInfo stockPageInfo = new PageInfo(stocks);
        if (stocks.isEmpty()) {
            stockPageInfo.setList(productVos);
            return stockPageInfo;
        }
        for (StockEntity stock : stocks) {
            //初始化回参实体
            OtherOutStockProductVo productVo = new OtherOutStockProductVo();
            //赋值
            BeanUtils.copyProperties(stock, productVo);
            //设置出库数量(默认为可申请数量)
            productVo.setOutStockQuantity(stock.getCanApplyQuantity());
            //设置库存数量
            productVo.setStockQuantity(stock.getRealQuantity());

            //设置库存id
            productVo.setStockId(stock.getId());

            //设置成本单价
            productVo.setStockCost(stock.getProductUnitPrice());
            //设置金额默认为0,计算方式为:(成本单价+分摊费用单价)*出库数量
            productVo.setCostSubtotal(new BigDecimal("0.00"));

            productVos.add(productVo);
        }

        stockPageInfo.setList(productVos);
        return stockPageInfo;
    }

    /**
     * 获取出库详情
     *
     * @param id   出库id
     * @param flag true:修改 false:详情
     * @return
     */
    public OtherOutStockVo getOtherOutStockDetailInfo(Integer id, boolean flag) {
        //初始化回参实体
        OtherOutStockVo vo = new OtherOutStockVo();
        if (null == id) {
            return vo;
        }

        //第一步：获取主表信息
        OtherOutStockEntity otherOutStock = otherOutStockService.queryById(id);
        if (null == otherOutStock || null == otherOutStock.getId()) {
            return vo;
        }
        //赋值
        BeanUtils.copyProperties(otherOutStock, vo);
        //设置出库时间
        vo.setOutStockDate(DateUtils.format(otherOutStock.getOutStockDate(), DateUtils.DATE_PATTERN));
        //设置创建时间
        vo.setCreateDate(DateUtils.format(otherOutStock.getCreateDate(), DateUtils.DATE_PATTERN));

        //第二步：获取对应产品信息
        OtherOutStockDetailEntity otherOutStockDetail = new OtherOutStockDetailEntity();
        //设置出库id
        otherOutStockDetail.setOutStockId(id);
        //设置数据为有效
        otherOutStockDetail.setValid(DataIsValidEnum.VALID.getId());
        List<OtherOutStockDetailEntity> otherOutStockDetails = otherOutStockDetailService.queryAll(otherOutStockDetail);
        if (!CollectionUtils.isEmpty(otherOutStockDetails)) {
            List<OtherOutStockDetailVo> productVos = otherOutStockDetails.stream().map(p -> {
                OtherOutStockDetailVo productVo = new OtherOutStockDetailVo();
                //赋值
                BeanUtils.copyProperties(p, productVo);
                return productVo;
            }).collect(Collectors.toList());

            vo.setDetailVos(productVos);
        }

        //第三步：获取附件信息
        AnnexEntity annex = new AnnexEntity();
        annex.setModuleId(ModuleTypeEnum.WAREHOUSE_OTHER_OUT_STOCK.getId());
        annex.setParentId(id);
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if (!CollectionUtils.isEmpty(annexList)) {
            List<AnnexVo> annexVos = annexList.stream().map(p -> {
                AnnexVo annexVo = new AnnexVo();
                //赋值
                BeanUtils.copyProperties(p, annexVo);
                //上传时间转换
                annexVo.setUploadTime(DateUtils.format(p.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置附件为旧附件,用以区分修改时附件状态
                annexVo.setNews(0);

                return annexVo;
            }).collect(Collectors.toList());

            vo.setAnnexVos(annexVos);
        }
        return vo;
    }

    /**
     * 设置仓库信息
     *
     * @param warehouseInfos 仓库信息集合
     * @param warehouseId    仓库编码
     */
    private String setWarehouse(List<DictionaryInfoRsp> warehouseInfos, String warehouseId) {
        if (CollectionUtils.isEmpty(warehouseInfos) || StringUtils.isBlank(warehouseId)) {
            return null;
        }
        for (DictionaryInfoRsp warehouseInfo : warehouseInfos) {
            if (warehouseInfo.getCode().equals(warehouseId)) {
                return warehouseInfo.getName();
            }
        }
        return null;
    }

    /**
     * 获取客户所有信息
     *
     * @return 客户所有信息
     */
    public List<CustomerInfoRsp> getCustomerAllInfo() {
        return otherOutStockService.getCustomerAllInfo(null, null, null);
    }

    /**
     * 通过客户编码获取客户联系人信息
     *
     * @param customCode 客户编码
     * @return 客户联系人
     */
    public List<CustomerContactRsp> getCustomerContactInfo(String customCode) {
        if (StringUtils.isBlank(customCode)) {
            return new ArrayList<>();
        }
        return otherOutStockService.getCustomerContactInfo(customCode);
    }


    /**
     * 获取String类型不为空数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private String getNotNullOfStringInfo(String value){
        if(StringUtils.isEmpty(value)){
            return "";
        }else {
            return value;
        }
    }

    /**
     * 获取BigDecimal类型不为空的数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private BigDecimal getNotNullOfBigDecimalInfo(BigDecimal value){
        if(StringUtil.isNotEmpty(value)){
            return value;
        }else {
            return new BigDecimal("0");
        }
    }


    /**
     * 获取所有用户信息
     *
     * @return 所有用户信息
     */
    public List<UserInfoRsp> getAllUserInfo() {
        return otherOutStockService.getAllUserInfo();
    }

    /**
     * 其它出库产品列表统计-分页
     *
     * @param req 查询条件
     * @return 其它出库产品列表统计
     */
    public PageInfo<OtherOutStockProductStatisticsVo> statisticsProductInfo(sellOutStockStatistics1Req req) {
        //初始化回参实体
        List<OtherOutStockProductStatisticsVo> voList = new ArrayList<>();
        List<OtherOutStockProductStatisticsRsp> statistics = otherOutStockDetailService.statisticsProductInfo(req);
        if (CollectionUtils.isEmpty(statistics)) {
            PageInfo pageInfo = new PageInfo();
            pageInfo.setList(voList);
            return pageInfo;
        }
        //获取分页信息
        PageInfo pageInfo = new PageInfo(statistics);
        for (OtherOutStockProductStatisticsRsp info : statistics) {
            //初始化回参对象
            OtherOutStockProductStatisticsVo vo = new OtherOutStockProductStatisticsVo();
            //赋值
            BeanUtils.copyProperties(info, vo);
            //出库日期
            vo.setOutStockDate(DateUtils.format(info.getOutStockDate()));
            //创建时间
            vo.setCreateDate(DateUtils.format(info.getCreateDate()));

            voList.add(vo);
        }
        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 其它出库产品列表统计-导出
     * @param req
     * @return
     */
    public JSONObject statisticsProductInfoExport(sellOutStockStatistics1Req req){
        //初始化回参实体
        List<OtherOutStockProductStatisticsVo> voList = new ArrayList<>();
        List<OtherOutStockProductStatisticsRsp> statistics = otherOutStockDetailService.statisticsProductInfo(req);
        for (OtherOutStockProductStatisticsRsp info : statistics) {
            //初始化回参对象
            OtherOutStockProductStatisticsVo vo = new OtherOutStockProductStatisticsVo();
            //赋值
            BeanUtils.copyProperties(info, vo);
            //出库日期
            vo.setOutStockDate(DateUtils.format(info.getOutStockDate()));
            //创建时间
            vo.setCreateDate(DateUtils.format(info.getCreateDate()));

            voList.add(vo);
        }
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleOtherOutStock();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(voList)){
            obj.put("data", data);
            return obj;
        }
        excelOtherOutStockExport(data,voList);
        obj.put("data", data);
        return obj;
    }
    public JSONArray getTitleOtherOutStock(){
        JSONArray obj=new JSONArray();
        obj.add("序号");
        obj.add("出库单号");
        obj.add("出库日期");
        obj.add("单位名称");
        obj.add("联系人");
        obj.add("联系人电话");
        obj.add("联系人地址");
        obj.add("出库人");
        obj.add("创建时间");
        obj.add("批次号");
        obj.add("产品编码");
        obj.add("规格编码");
        obj.add("产品单位");
        obj.add("仓库名称");
        obj.add("出库数量");
        obj.add("中文名称");
        obj.add("英文名称");
        obj.add("中文描述");
        obj.add("英文描述");
        obj.add("托盘入数");
        obj.add("总托盘");
        return obj;
    }


    public void excelOtherOutStockExport(JSONArray data,List<OtherOutStockProductStatisticsVo>  list ){
        //出库数量
        BigDecimal outStockQuantity = new BigDecimal(0);
        //托盘入数
        BigDecimal trayNumber = new BigDecimal(0);
        //总托盘
        BigDecimal totalTray = new BigDecimal(0);

        Integer i=0;
        for (OtherOutStockProductStatisticsVo vo: list) {
            JSONArray infoList = new JSONArray();
            infoList.add(++i);
            infoList.add(getNotNullOfStringInfo(vo.getBillNo()));
            infoList.add(getNotNullOfStringInfo(vo.getOutStockDate()));
            infoList.add(getNotNullOfStringInfo(vo.getReceiptCompanyName()));
            infoList.add(getNotNullOfStringInfo(vo.getContactPerson()));
            infoList.add(getNotNullOfStringInfo(vo.getContactPersonPhone()));
            infoList.add(getNotNullOfStringInfo(vo.getContactPersonAddress()));
            infoList.add(getNotNullOfStringInfo(vo.getOutStockPerson()));
            infoList.add(getNotNullOfStringInfo(vo.getCreateDate()));
            infoList.add(getNotNullOfStringInfo(vo.getLotNo()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCode()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecificationCode()));
            infoList.add(getNotNullOfStringInfo(vo.getProductUnit()));
            infoList.add(getNotNullOfStringInfo(vo.getWarehouseName()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getOutStockQuantity()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCname()));
            infoList.add(getNotNullOfStringInfo(vo.getProductEname()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCdesc()));
            infoList.add(getNotNullOfStringInfo(vo.getProductEdesc()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTrayNumber()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalTray()));


            if(vo.getOutStockQuantity()!=null){
                outStockQuantity = outStockQuantity.add(vo.getOutStockQuantity());
            }
            if(vo.getTrayNumber()!=null){
                trayNumber = trayNumber.add(vo.getTrayNumber());
            }
            if(vo.getTotalTray()!=null){
                totalTray = totalTray.add(vo.getTotalTray());
            }
            data.add(infoList);
        }
        //合计
        JSONArray infoList = new JSONArray();
        infoList.add("合计");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add(outStockQuantity);
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add(trayNumber);
        infoList.add(totalTray);
        data.add(infoList);
    }



}
